home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / as / sprite / app.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-27  |  7.4 KB  |  378 lines

  1. /* This is the Assembler Pre-Processor
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* App, the assembler pre-processor.  This pre-processor strips out excess
  21.    spaces, turns single-quoted characters into a decimal constant, and turns
  22.    # <number> <filename> <garbage> into a .line <number>;.file <filename> pair.
  23.    This needs better error-handling.
  24.  */
  25. #include <stdio.h>
  26. #ifdef USG
  27. #define bzero(s,n) memset(s,0,n)
  28. #endif
  29.  
  30. static char    lex [256];
  31. static char    symbol_chars[] = 
  32.     "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  33.  
  34. extern char comment_chars[];
  35. extern char line_comment_chars[];
  36.  
  37. #define LEX_IS_SYMBOL_COMPONENT        (1)
  38. #define LEX_IS_WHITESPACE        (2)
  39. #define LEX_IS_LINE_SEPERATOR        (4)
  40. #define LEX_IS_COMMENT_START        (8)    /* JF added these two */
  41. #define LEX_IS_LINE_COMMENT_START    (16)
  42. #define IS_SYMBOL_COMPONENT(c)        (lex [c] & LEX_IS_SYMBOL_COMPONENT)
  43. #define IS_WHITESPACE(c)        (lex [c] & LEX_IS_WHITESPACE)
  44. #define IS_LINE_SEPERATOR(c)        (lex [c] & LEX_IS_LINE_SEPERATOR)
  45. #define IS_COMMENT(c)            (lex [c] & LEX_IS_COMMENT_START)
  46. #define IS_LINE_COMMENT(c)        (lex [c] & LEX_IS_LINE_COMMENT_START)
  47.  
  48. void
  49. do_scrub_begin()
  50. {
  51.     char *p;
  52.  
  53.     bzero (lex, sizeof(lex));        /* Trust NOBODY! */
  54.     lex [' ']        |= LEX_IS_WHITESPACE;
  55.     lex ['\t']        |= LEX_IS_WHITESPACE;
  56.     for (p =symbol_chars;*p;++p)
  57.         lex [*p] |= LEX_IS_SYMBOL_COMPONENT;
  58.     lex ['\n']        |= LEX_IS_LINE_SEPERATOR;
  59. #ifdef DONTDEF
  60.     lex [':']        |= LEX_IS_LINE_SEPERATOR;
  61. #endif
  62.     lex [';']        |= LEX_IS_LINE_SEPERATOR;
  63.     for (p=comment_chars;*p;p++)
  64.         lex[*p] |= LEX_IS_COMMENT_START;
  65.     for (p=line_comment_chars;*p;p++)
  66.         lex[*p] |= LEX_IS_LINE_COMMENT_START;
  67. }
  68.  
  69. FILE *scrub_file;
  70.  
  71. int
  72. scrub_from_file()
  73. {
  74.     return getc(scrub_file);
  75. }
  76.  
  77. void
  78. scrub_to_file(ch)
  79. int ch;
  80. {
  81.     ungetc(ch,scrub_file);
  82. }
  83.  
  84. char *scrub_string;
  85. char *scrub_last_string;
  86.  
  87. int
  88. scrub_from_string()
  89. {
  90.     return scrub_string == scrub_last_string ? EOF : *scrub_string++;
  91. }
  92.  
  93. void
  94. scrub_to_string(ch)
  95. int ch;
  96. {
  97.     *--scrub_string=ch;
  98. }
  99.  
  100. int
  101. do_scrub_next_char(get,unget)
  102. int (*get)();
  103. void (*unget)();
  104. /* FILE *fp; */
  105. {
  106.     /* State 0: beginning of normal line
  107.         1: After first whitespace on normal line (flush more white)
  108.         2: After first non-white on normal line (keep 1white)
  109.         3: after second white on normal line (flush white)
  110.         4: after putting out a .line, put out digits
  111.         5: parsing a string, then go to old-state
  112.         6: putting out \ escape in a "d string.
  113.         7: After putting out a .file string, flush until newline.
  114.         -1: output string in out_string and go to the state in old_state
  115.         -2: flush text until a '*' '/' is seen, then go to state old_state
  116.     */
  117.  
  118.     static state;
  119.     static old_state;
  120.     static char *out_string;
  121.     static char out_buf[20];
  122.     static add_newlines = 0;
  123.     static in_cpp_comment = 0;
  124.     int ch;
  125.  
  126.     if(state==-1) {
  127.         ch= *out_string++;
  128.         if(*out_string==0) {
  129.             state=old_state;
  130.             old_state=3;
  131.         }
  132.         return ch;
  133.     }
  134.     if(state==-2) {
  135.         do ch=(*get)();
  136.         while(ch!=EOF && ch!='\n' && (ch!='*' || (*get)()!='/'));
  137.         if(ch=='\n' || ch==EOF)
  138.             return ch;
  139.         else {
  140.             state=old_state;
  141.             return ' ';
  142.         }
  143.     }
  144.     if(state==4) {
  145.         ch=(*get)();
  146.         if(ch==EOF || (ch>='0' && ch<='9'))
  147.             return ch;
  148.         else {
  149.             while(ch!=EOF && IS_WHITESPACE(ch))
  150.                 ch=(*get)();
  151.             if(ch=='"') {
  152.                 (*unget)(ch);
  153.                 out_string="; .file ";
  154.                 old_state=3;
  155.                 state= -1;
  156.                 return *out_string++;
  157.             } else {
  158.                 while(ch!=EOF && ch!='\n')
  159.                     ch=(*get)();
  160.                 in_cpp_comment = 0;
  161.                 return ch;
  162.             }
  163.         }
  164.     }
  165.     if(state==5) {
  166.         ch=(*get)();
  167.         if(ch=='"') {
  168.             state=old_state;
  169.             if (in_cpp_comment) {
  170.                 while(ch!=EOF && ch!='\n') {
  171.                 ch=(*get)();
  172.                 }
  173.                 (*unget)(ch);
  174.             }
  175.             return '"';
  176.         } else if(ch=='\\') {
  177.             state=6;
  178.             return ch;
  179.         } else if(ch==EOF) {
  180.             as_fatal("End of file in string");
  181.             return 0;
  182.         } else {
  183.             return ch;
  184.         }
  185.     }
  186.     if(state==6) {
  187.         state=5;
  188.         ch=(*get)();
  189.         switch(ch) {
  190.             /* This is neet.  Turn "string
  191.                more string" into "string\n  more string"
  192.              */
  193.         case '\n':
  194.             (*unget)('n');
  195.             add_newlines++;
  196.             return '\\';
  197.  
  198.         case '"':
  199.         case '\\':
  200.         case 'b':
  201.         case 'f':
  202.         case 'n':
  203.         case 'r':
  204.         case 't':
  205.         case '0':
  206.         case '1':
  207.         case '2':
  208.         case '3':
  209.         case '4':
  210.         case '5':
  211.         case '6':
  212.         case '7':
  213.             break;
  214.         default:
  215.             as_warn("Unknown escape '\\%c' in string",ch);
  216.             break;
  217.  
  218.         case EOF:
  219.             as_warn("End of file in string: '\"' inserted");
  220.             return '"';
  221.         }
  222.         return ch;
  223.     }
  224.  
  225.  flushchar:
  226.     ch=(*get)();
  227.     switch(ch) {
  228.     case ' ':
  229.     case '\t':
  230.         do ch=(*get)();
  231.         while(ch!=EOF && IS_WHITESPACE(ch));
  232.         if(ch==EOF)
  233.             return ch;
  234.         if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) {
  235.             (*unget)(ch);
  236.             goto flushchar;
  237.         }
  238.         (*unget)(ch);
  239.         if(state==0 || state==2) {
  240.             state++;
  241.             return ' ';
  242.         } else goto flushchar;
  243.  
  244.     case '/':
  245.         ch=(*get)();
  246.         if(ch=='*') {
  247.             for(;;) {
  248.                 do {
  249.                     ch=(*get)();
  250.                     if(ch=='\n')
  251.                         add_newlines++;
  252.                 } while(ch!=EOF && ch!='*');
  253.                 ch=(*get)();
  254.                 if(ch==EOF || ch=='/')
  255.                     break;
  256.                 (*unget)(ch);
  257.             }
  258.             if(ch==EOF)
  259.                 as_warn("End of file in '/' '*' string");
  260.  
  261.             (*unget)(' ');
  262.             goto flushchar;
  263.         } else {
  264.             if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) {
  265.                     (*unget)(ch);
  266.                 ch='/';
  267.                 goto deal_misc;
  268.             }
  269.             if(ch!=EOF)
  270.                 (*unget)(ch);
  271.             return '/';
  272.         }
  273.         break;
  274.  
  275.     case '"':
  276.         old_state=state;
  277.         state=5;
  278.         return '"';
  279.         break;
  280.  
  281.     case '\'':
  282.         ch=(*get)();
  283.         if(ch==EOF) {
  284.             as_warn("End-of-file after a '");
  285.             ch=0;
  286.         }
  287.         sprintf(out_buf,"(%d)",ch&0xff);
  288.         old_state=state;
  289.         state= -1;
  290.         out_string=out_buf;
  291.         return *out_string++;
  292.  
  293.     case ':':
  294.         if(state!=3)
  295.             state=0;
  296.         return ch;
  297.  
  298.     case '\n':
  299.         if(add_newlines) {
  300.             --add_newlines;
  301.             (*unget)(ch);
  302.         }
  303.     case ';':
  304.         state=0;
  305.         return ch;
  306.  
  307.     default:
  308.     deal_misc:
  309.         if(state==0 && IS_LINE_COMMENT(ch)) {
  310.             do ch=(*get)();
  311.             while(ch!=EOF && IS_WHITESPACE(ch));
  312.             if(ch==EOF) {
  313.                 as_warn("Unexpected EOF in comment");
  314.                 return '\n';
  315.             }
  316.             if(ch<'0' || ch>'9') {
  317.                 do ch=(*get)();
  318.                 while(ch!=EOF && ch!='\n');
  319.                 if(ch==EOF)
  320.                     as_warn("Unexpected EOF in Comment");
  321.                 state=0;
  322.                 return '\n';
  323.             }
  324.             (*unget)(ch);
  325.             old_state=4;
  326.             state= -1;
  327.             out_string=".line ";
  328.             in_cpp_comment = 1;
  329.             return *out_string++;
  330.  
  331.         } else if(IS_COMMENT(ch)) {
  332.             do ch=(*get)();
  333.             while(ch!=EOF && ch!='\n');
  334.             if(ch==EOF)
  335.                 as_warn("Unexpected EOF in comment");
  336.             state=0;
  337.             return '\n';
  338.  
  339.         } else if(state==0) {
  340.             state=2;
  341.             return ch;
  342.         } else if(state==1) {
  343.             state=2;
  344.             return ch;
  345.         } else {
  346.             return ch;
  347.  
  348.         }
  349.     case EOF:
  350.         if(state==0)
  351.             return ch;
  352.         as_warn("End-of-File not at end of a line");
  353.     }
  354.     return -1;
  355. }
  356.  
  357. #ifdef TEST
  358.  
  359. char comment_chars[] = "|";
  360. char line_comment_chars[] = "#";
  361.  
  362. main()
  363. {
  364.     int    ch;
  365.  
  366.     app_begin();
  367.     while((ch=do_scrub_next_char(stdin))!=EOF)
  368.         putc(ch,stdout);
  369. }
  370.  
  371. as_warn(str)
  372. char *str;
  373. {
  374.     fputs(str,stderr);
  375.     putc('\n',stderr);
  376. }
  377. #endif
  378.